<script setup lang="ts">
import { onMounted, ref, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus'
import AMapLoader from "@amap/amap-jsapi-loader";
import { mapSetting } from "#/api/map";
const getImageUrl = (name: string) => {
  return new URL(`../../../../../assets/${name}`, import.meta.url).href
}
const props = defineProps({
  deviceData: Object,
  // receivedData: Array
});
const emit = defineEmits(['send-data'])
const sendData = (data) => {
  // const { lnglat, distances } = data
  emit('send-data', data)
}
let canFly = ref(true);
let map;
let centerlnglat;
let marker, marker2, polyline, airportMarker;
let contextMenu;
let lnglat;
let distances;
let hangxian_ing = ref(false);
let mapContainer = ref(null);
let planeRotation = 0; // 初始朝向
const marker_angle = 0; // 初始朝向偏移量
const loadAMap = async () => {
  // return new Promise((resolve, reject) => {
  //   if (window.AMap) {
  //     resolve(window.AMap);
  //     return;
  //   }

  //   const script = document.createElement('script');
  //   script.src = `https://webapi.amap.com/maps?v=2.0&key=ce77626588b7a2ee836159f48dd4a1a6`;
  //   script.addEventListener('load', () => resolve(window.AMap));
  //   script.onerror = reject;
  //   document.head.append(script);
  // });
  try {
    const AMap = await AMapLoader.load({
      key: mapSetting.mapKey,
      securityJsCode: mapSetting.mapSecurity,
      version: "2.0",
    });
    centerlnglat = props.deviceData.longitude ? [props.deviceData.longitude, props.deviceData.latitude] : [119.904792, 30.247956]
    if (!map) {
      map = new AMap.Map(mapContainer.value, {
        zoom: 15,
        center: centerlnglat,
        pitch: 0, // 俯仰角度
        viewMode: '3D', // 启用 3D 模式
        layers: [
          // 卫星
          new AMap.TileLayer.Satellite(),
          // 路网
          new AMap.TileLayer.RoadNet(),
        ],
      });
    }
    if (!marker) {
      marker = new AMap.Marker({
        position: centerlnglat,
        icon: new AMap.Icon({
          // image: '../../../../../assets/aircraft_logo.png',
          image: getImageUrl('aircraft_logo.png'),
          size: new AMap.Size(40, 40),
          imageSize: new AMap.Size(40, 40),
        }),
        offset: new AMap.Pixel(-20, -20),
        angle: planeRotation + marker_angle,
        autoRotation: false,
      })
      map.add(marker);
    }
    if (!airportMarker && props.deviceData?.longitude) {
      airportMarker = new AMap.Marker({
        position: [props.deviceData.longitude, props.deviceData.latitude],
        icon: new AMap.Icon({
          // image: '../../../../../assets/airport_logo.png',
          image: getImageUrl('airport_logo.png'),
          size: new AMap.Size(48, 48),
          imageSize: new AMap.Size(48, 48),
        }),
        offset: new AMap.Pixel(-24, -24),
        autoRotation: false,
      })
      map.add(airportMarker);
    }
    // markers.push(marker)
    map.add(marker);
    map.setFitView()
  } catch (error) {
    console.error("地图初始化失败:", error);
    ElMessage.error("地图初始化失败: " + error.message);
  }
};
function moveMarkerTo(marker, newPosition, duration = 2000) {
  const startPos = marker.getPosition();
  const startTime = Date.now();
  function animate() {
    const elapsed = Date.now() - startTime;
    const progress = Math.min(elapsed / duration, 1);
    // 计算中间位置
    const currentLng = startPos.lng + (newPosition.lng - startPos.lng) * progress;
    const currentLat = startPos.lat + (newPosition.lat - startPos.lat) * progress;
    marker.setPosition([currentLng, currentLat]);
    if (progress < 1) {
      requestAnimationFrame(animate);
    }
  }
  animate();
}
/**
 * 使用 Vincenty 公式计算两个经纬度之间的高精度距离（单位：米）
 * @param {Array<number>} coord1 - [纬度1, 经度1]
 * @param {Array<number>} coord2 - [纬度2, 经度2]
 * @returns {number} 两点之间的距离（米）
 * @throws {Error} 如果参数无效或计算不收敛
 */
function getPreciseDistance(coord1, coord2) {
  // 参数校验
  if (!Array.isArray(coord1) || !Array.isArray(coord2)) {
    throw new Error("参数必须是数组 [经度, 纬度]");
  }
  if (coord1.length !== 2 || coord2.length !== 2) {
    throw new Error("坐标格式错误，应为 [经度, 纬度]");
  }

  const [lon1, lat1] = coord1.map(Number); // 现在第一个是经度，第二个是纬度
  const [lon2, lat2] = coord2.map(Number);

  // 检查经纬度范围
  if (lat1 < -90 || lat1 > 90 || lat2 < -90 || lat2 > 90) {
    throw new Error("纬度必须在 -90 到 90 度之间");
  }
  if (lon1 < -180 || lon1 > 180 || lon2 < -180 || lon2 > 180) {
    throw new Error("经度必须在 -180 到 180 度之间");
  }

  // WGS84 椭球参数
  const a = 6378137.0; // 地球长半轴（米）
  const b = 6356752.314245; // 地球短半轴（米）
  const f = (a - b) / a; // 扁率

  const φ1 = lat1 * Math.PI / 180; // 纬度1（弧度）
  const φ2 = lat2 * Math.PI / 180; // 纬度2（弧度）
  const λ1 = lon1 * Math.PI / 180; // 经度1（弧度）
  const λ2 = lon2 * Math.PI / 180; // 经度2（弧度）

  const L = λ2 - λ1; // 经度差
  const U1 = Math.atan((1 - f) * Math.tan(φ1)); // 辅助计算
  const U2 = Math.atan((1 - f) * Math.tan(φ2)); // 辅助计算

  let λ = L;
  let λPrev; // 初始化 λPrev
  let sinσ, cosσ, σ, sinα, cosSqα, cos2σM;
  let iterations = 0;
  const maxIterations = 200;

  do {
    λPrev = λ; // 存储当前 λ 值用于下一次比较

    const sinU1 = Math.sin(U1);
    const cosU1 = Math.cos(U1);
    const sinU2 = Math.sin(U2);
    const cosU2 = Math.cos(U2);

    sinσ = Math.sqrt(
      (cosU2 * Math.sin(λ)) ** 2 +
      (cosU1 * sinU2 - sinU1 * cosU2 * Math.cos(λ)) ** 2
    );

    if (sinσ === 0) return 0; // 两点重合

    cosσ = sinU1 * sinU2 + cosU1 * cosU2 * Math.cos(λ);
    σ = Math.atan2(sinσ, cosσ);
    sinα = (cosU1 * cosU2 * Math.sin(λ)) / sinσ;
    cosSqα = 1 - sinα ** 2;
    cos2σM = cosσ - (2 * sinU1 * sinU2) / cosSqα;

    if (isNaN(cos2σM)) cos2σM = 0; // 赤道情况

    const C = (f / 16) * cosSqα * (4 + f * (4 - 3 * cosSqα));
    λ = L + (1 - C) * f * sinα *
      (σ + C * sinσ * (cos2σM + C * cosσ * (-1 + 2 * cos2σM ** 2)));

    iterations++;
    if (iterations > maxIterations) {
      throw new Error("Vincenty 公式计算不收敛");
    }
  } while (Math.abs(λ - λPrev) > 1e-12);

  const uSq = cosSqα * (a ** 2 - b ** 2) / (b ** 2);
  const A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
  const B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
  const Δσ = B * sinσ * (
    cos2σM + B / 4 * (
      cosσ * (-1 + 2 * cos2σM ** 2) -
      B / 6 * cos2σM * (-3 + 4 * sinσ ** 2) * (-3 + 4 * cos2σM ** 2)
    )
  );

  const s = b * A * (σ - Δσ); // 最终距离（米）
  return s;
}
const fly_here = () => {
  contextMenu.close()
  // if (!hangxian_ing.value) {
  ElMessageBox.confirm(
    '确认飞至此处',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
    }
  ).then(() => {
    lnglat = l_s_lnglat;
    // ElMessage({
    //   type: 'success',
    //   message: 'Delete completed',
    // })
    // centerlnglat = lnglat;
    // map.setCenter(centerlnglat);
    // marker.setPosition(centerlnglat)
    // moveMarkerTo(marker, centerlnglat)
    create_m_l()
    //发送坐标数据给socket
    sendData({ lnglat, ing: hangxian_ing.value });
    hangxian_ing.value = true
  }).catch(() => {
    contextMenu.close()
  })
  // } else {
  //   ElMessage('请等待任务结束后再试')
  // }
}
const create_m_l = () => {
  const newlnglat = [lnglat.KL, lnglat.kT]
  if (marker2) marker2.setMap(null)
  marker2 = new AMap.Marker({
    position: [lnglat.KL, lnglat.kT],
    // icon: '//webapi.amap.com/theme/v1.3/markers/b/mark_bs.png'
  })
  if (polyline) {
    polyline.setPath([newlnglat, centerlnglat])
    polyline.show()
  } else {
    polyline = new AMap.Polyline({
      path: [newlnglat, centerlnglat],
      isOutline: true,
      outlineColor: '#ffeeff',
      borderWeight: 3,
      strokeColor: "#3366FF",
      strokeOpacity: 1,
      strokeWeight: 1,
      // 折线样式还支持 'dashed'
      strokeStyle: "dashed",
      // strokeStyle是dashed时有效
      strokeDasharray: [10, 2, 10],
      lineJoin: 'round',
      lineCap: 'round',
      zIndex: 50,
    })
  }
  map.add([marker2, polyline]);
  map.setFitView()
}
const update_mark_line = (newValue) => {
  // map.setCenter(newValue);
  if (marker) {
    marker.setPosition(newValue);
  }
  if (hangxian_ing.value) {
    if (marker) {
      map.setFitView()
    }
    const newlnglat = [lnglat.KL, lnglat.kT]
    if (polyline) {
      polyline.setPath([newlnglat, newValue])
      map.setFitView()
    }
    // distances = getPreciseDistance(newlnglat, newValue);
    if (getPreciseDistance(newlnglat, newValue) < 1) {
      // hangxian_ing.value = false;
      // distances = 0;
      // 执行完成
      if (polyline) polyline.hide()
      if (marker2) marker2.setMap(null)
      // ElMessage({
      //   message: '',
      //   type: 'success',
      // })
      // sendData({ distances })
    } else {
      // sendData({ distances })
    }
  } else {
    if (polyline) polyline.hide()
    if (marker2) marker2.setMap(null)
  }
}
const set_marker_setAngle = () => {
  // console.log(marker)
  if (marker) {
    marker.setAngle(planeRotation + marker_angle)
  }
}
let map_loading = true
let l_s_lnglat;
onMounted(async () => {
  try {
    await loadAMap();
    // setTimeout(() => {
    map_loading = false
    // }, 1000);
    // centerlnglat = props.deviceData.longitude ? [props.deviceData.longitude, props.deviceData.latitude] : [119.904792, 30.247956]
    // if (!map) {
    //   map = new AMap.Map('map-container', {
    //     zoom: 18,
    //     center: centerlnglat,
    //     pitch: 0, // 俯仰角度
    //     viewMode: '3D', // 启用 3D 模式
    //     resizeEnable: true,
    //     layers: [
    //       // 卫星
    //       new AMap.TileLayer.Satellite(),
    //       // 路网
    //       new AMap.TileLayer.RoadNet(),
    //     ],
    //   });
    // }
    // if (!marker) {
    //   marker = new AMap.Marker({
    //     position: centerlnglat,
    //   })
    //   map.add(marker);
    // }
    AMap.plugin(['AMap.MouseTool'], () => {
      // ContextMenu(map);
      contextMenu = new AMap.ContextMenu(map);
      contextMenu.addItem("飞至此处", function () {
        fly_here()
      }, 0);
      map.on('rightclick', function (e) {
        if (canFly.value) {
          if (!contextMenu) contextMenu = new AMap.ContextMenu(map);
          // 鼠标点击位置赋值
          l_s_lnglat = e.lnglat;
          contextMenu.open(map, e.lnglat);
        }
      });
    });
  } catch (error) {
    console.error('地图加载失败:', error);
  }
});
const childMethod = (param) => {
  if (!map_loading && param.attitudeHead) {
    planeRotation = param.attitudeHead
    set_marker_setAngle()
    // 设置角度
  }
  let newValue = param.mapcenter
  if (!map_loading && newValue[0]) {
    if (centerlnglat != newValue) {
      centerlnglat = newValue;
      // console.log(newValue)
      // moveMarkerTo(marker, centerlnglat)
      // marker.setPosition(newValue)
      update_mark_line(newValue)
    };
  }
}
const childMethod2 = (data) => {
  // hangxian_ing.value = false;
  if (data.type == 'takeoff_to_point_progress') {
    // 一键起飞结果事件通知
    // console.log('一键起飞', data.data.status)
    if (data.data.status == 'wayline_progress') canFly.value = false
    if (data.data.status == 'wayline_ok') canFly.value = true
  }
  if (data.type == 'fly_to_point_progress') {
    // flyto 执行结果事件通知
    // console.log('指点飞行', data.data.status)
    if (data.data.status == 'wayline_progress') hangxian_ing.value = true
    if (data.data.status == 'wayline_ok') hangxian_ing.value = false
    if (data.data.status == 'wayline_failed') {
      ElMessage({
        message: '操作太频繁了，请重试',
        type: 'warning',
      })
      hangxian_ing.value = false;
    } else {
      distances = data.data.remaining_distance;
      sendData({ distances })
    }
  }
}
defineExpose({
  childMethod, childMethod2
})
</script>
<template>
  <div class="map-box">
    <div class="map-title">{{ hangxian_ing ? '指点飞行' : '航图展示' }} <span>{{ deviceData.airportName }}</span></div>
    <div class="map-k">
      <div class="map" id="map-container" ref="mapContainer"></div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
:deep(.amap-logo) {
  display: none !important;
}

:deep(.amap-copyright) {
  display: none !important;
}

.map-box {
  height: 100%;

  .map-title {
    width: 100%;
    height: 4vh;
    font-family: PingFangSC, 'PingFang SC';
    font-size: 1.8vh;
    font-style: normal;
    font-weight: 500;
    line-height: 4vh;
    color: #fffefe;
    padding-left: 1vh;
    display: flex;
    align-items: center;

    span {
      font-weight: 400;
      padding-left: 1vh;
      font-size: 1.5vh;
    }
  }

  .map-k {
    position: relative;
    width: 100%;
    height: calc(100% - 5vh);
    overflow: hidden;

    .map {
      // position: absolute;
      // right: 0;
      // bottom: 0;
      // left: 0;
      width: 100%;
      height: calc(100%);

      :deep(.context_menu) {
        position: relative;
        background-color: #3781cc;
        font-size: 1.6vh;
        padding: 1vh 1vh;
        color: #FFFFFF;
        cursor: pointer;
      }

      :deep(.context_menu:hover) {
        background-color: #4f8ecc;
      }

      :deep(.amap-menu) {
        background-color: #3781cc;
      }

      :deep(.amap-menu-outer) {
        background: #3781cc;
      }

      :deep(ul.amap-menu-outer li:hover) {
        background-color: #4f8ecc;
        background: #4f8ecc;
      }
    }
  }
}
</style>
